package top.liujiachen.springboot.shiro.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.JWTValidator;
import cn.hutool.jwt.RegisteredPayload;
import cn.hutool.jwt.signers.JWTSignerUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.UUID;

@Component
public class TokenUtil {

    private static Logger LOGGER = LoggerFactory.getLogger(TokenUtil.class);

    private static SymmetricCrypto AES = new SymmetricCrypto(SymmetricAlgorithm.AES, SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded());

    private static String KEY;

    private static byte[] HS256_KEY;

    private static long EXP_TIME;

    @Value("${app.jwt.key}")
    public void setKEY(String KEY) {
        TokenUtil.KEY = KEY;
        TokenUtil.HS256_KEY = SecureUtil.md5(KEY).getBytes();
    }

    @Value("${app.jwt.exp-time}")
    public void setExpTime(long expTime) {
        EXP_TIME = expTime;
    }

    public static String token(String username, String secret) {
        if (StringUtils.isBlank(username)) {
            throw new RuntimeException("username is not null");
        }
        if (StringUtils.isBlank(secret)) {
            throw new RuntimeException("secret is not null");
        }
        return JWT.create()
                .setJWTId(UUID.randomUUID().toString())
                .setIssuedAt(DateUtil.date())
                .setSubject(AES.encryptHex(username))
                .setExpiresAt(DateUtil.date(System.currentTimeMillis() + EXP_TIME))
                .setPayload("secret", AES.encryptBase64(secret))
                .setKey(HS256_KEY)
                .sign();
    }

    public static String getUsername(String token) {
        JWT jwt =  JWTUtil.parseToken(token);
        return AES.decryptStr((String) jwt.getPayload(RegisteredPayload.SUBJECT));
    }

    public static String getSecret(String token) {
        JWT jwt =  JWTUtil.parseToken(token);
        return AES.decryptStr((String) jwt.getPayload("secret"));
    }

    public static boolean verify(String token) {
        try {
            JWTValidator
                    .of(token)
                    .validateDate(DateUtil.date())
                    .validateAlgorithm(JWTSignerUtil.hs256(HS256_KEY));
        } catch (ValidateException e) {
            LOGGER.error("Line: 52", e);
            return false;
        } catch (Exception e) {
            LOGGER.error("Line: 56", e);
            return false;
        }
        return JWTUtil.verify(token, HS256_KEY);
    }

}
